package logservice

import (
	"time"
	"yunj/pkg/global"
	"yunj/pkg/yunj/app/dto"
	"yunj/pkg/yunj/app/queue"
	"yunj/pkg/yunj/app/service/admin/adminservice"
	"yunj/pkg/yunj/app/service/admin/logdbservice"
	"yunj/pkg/yunj/util"

	"github.com/gin-gonic/gin"
)

// 日志追加参数
type AppendArgs struct {
	MemberId        uint64    // 操作成员id
	DataId          string    // 操作数据id
	Desc            string    // 操作描述
	ResponseContent string    // 响应内容
	EndTime         time.Time // 结束时间（用于计算耗时）
}

// 记录日志
func Record(ctx *gin.Context, args ...AppendArgs) {
	var logParam *dto.AdminMemberLogRecordParam
	logParamRaw, exists := ctx.Get("logParam")
	if exists && logParamRaw != nil {
		if logParamValue, ok := logParamRaw.(*dto.AdminMemberLogRecordParam); ok {
			logParam = logParamValue
		}
	}
	if logParam == nil {
		logParam = &dto.AdminMemberLogRecordParam{
			Method:    ctx.Request.Method,
			Ip:        ctx.ClientIP(),
			CreatedAt: time.Now().In(time.Local).Format("2006-01-02 15:04:05"),
			UserAgent: ctx.Request.UserAgent(),
			StartTime: time.Now().In(time.Local),
		}
		// id
		id, err := util.SnowflakeId()
		if err != nil {
			global.Logger.Error(util.FormatError(err, "日志记录：生成id错误！"))
			return
		}
		logParam.Id = id
		// url
		var url string
		urlR := []rune(ctx.Request.URL.String())
		if len(urlR) > 200 {
			urlR = urlR[:195]
			url = string(urlR) + "..."
		} else {
			url = string(urlR)
		}
		logParam.Url = url
		// request_params
		requestParams, err := util.GetAllParams(ctx)
		if err != nil {
			global.Logger.Error(util.FormatError(err, "日志记录：获取请求参数错误！"))
		}
		if len(requestParams) > 0 {
			truncateRequestParams := util.TruncateValue(requestParams, 200)
			truncateRequestParamsJson, err := util.ToJson(truncateRequestParams)
			if err != nil {
				global.Logger.WithField("truncateRequestParams", truncateRequestParams).Error(util.FormatError(err, "日志记录：缩短的请求参数json转换错误！"))
			}
			logParam.RequestParams = truncateRequestParamsJson
		}
	}
	// 补充追加参数
	for _, arg := range args {
		if arg.MemberId > 0 {
			logParam.MemberId = arg.MemberId
		}
		if arg.DataId != "" {
			logParam.DataId = arg.DataId
		}
		if arg.Desc != "" {
			logParam.Desc = arg.Desc
		}
		if arg.ResponseContent != "" {
			logParam.ResponseContent = arg.ResponseContent
		}
		// 计算耗时
		if !arg.EndTime.IsZero() {
			logParam.Latency = util.MsTimeDiff(logParam.StartTime, arg.EndTime)
		}
	}
	// 当前权限
	if requestAuth := adminservice.GetRequestAuth(ctx); requestAuth != nil {
		logParam.AuthKey = requestAuth.Key
		if logParam.Desc == "" {
			logParam.Desc = requestAuth.FullName
		}
	}
	// 登录成员id
	if logParam.MemberId == 0 {
		logParam.MemberId = adminservice.GetLoginMemberId(ctx)
	}
	ctx.Set("logParam", logParam)
	// 推送队列
	err := queue.AdminLog.Push(logParam)
	if err == nil {
		return
	}

	global.Logger.WithField("logParam", logParam).Error(util.FormatError(err, "日志记录队列推送失败！"))
	// 推送队列不成功，直接保存到数据库
	err = logdbservice.Save(logParam)
	if err != nil {
		global.Logger.WithField("logParam", logParam).Error(util.FormatError(err, "日志记录数据库保存失败！"))
	}
}
